Add defang identity: agent public-key registration - #2167
Conversation
New command group for the agent-identity key registry (OpenAuth as a per-tenant OIDC public-key registry, DefangLabs/openauth PR 8): - defang identity register: generate an RS256 keypair (private key stays under the state dir, one key per tenant/project/stack), sign the proof-of-possession JWT, and POST the public JWK to the tenant registry - defang identity list / revoke: manage registered keys pkg/identity owns keypair handling and the registry HTTP client; the bearer token is the OpenAuth access token saved by defang login, and the tenant URL is derived from DEFANG_ISSUER + the WhoAmI tenant label. go-jose (already indirect) is promoted to direct for JWK marshaling and the RFC 7638 thumbprint. Verified end-to-end against the live spike registry: register, idempotent re-register, cross-stack key-reuse 409, list, revoke. Addresses issue 2166. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R9PbZ9nkj1RxubjnxujXPa
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Picking up the other halves of this spike (registry: DefangLabs/portal#1011, Fabric: DefangLabs/defang-mvp#3174) turned up a break in this branch worth fixing before it comes out of draft.
The fix is not to swap in Two smaller notes for the same pass:
|
Draft implementation for #2166 — CLI half of the agent-identity key registry (DefangLabs/openauth PR 8): agents hold a local keypair and register only the public half with the per-tenant OIDC registry, then federate into clouds with self-signed JWTs instead of long-lived credentials.
What's added
defang identity register— generates an RS256 keypair on first use (private key stays in<state-dir>/identity/<tenant>/<project>/<stack>/private.pem, mode 0600, one key per pair because the registry rejects cross-stack key reuse), signs the proof-of-possession JWT, and POSTs the public JWK tohttps://<tenant>.<issuer-host>/keys. Project and stack come from the normal session machinery (no cloud-provider auth needed, soCheckAccountInfois off); the bearer is the OpenAuth token saved bydefang login; the issuer comes fromDEFANG_ISSUER.defang identity list/defang identity revoke KID— the GET/DELETE endpoints.pkg/identity— keypair handling (RS256: AWS OIDC federation doesn't accept Ed25519) and the registry HTTP client. RFC 7638 thumbprint viago-jose(promoted indirect → direct; no new deps), PoP JWT via the existinggolang-jwt/v5.pkg/http/delete.go—DeleteWithHeader/DeleteWithAuth, mirroring the existing GET helpers.auth.Client.Issuer()accessor so the tenant URL can be derived without re-reading the env var.Verification
go test -short ./...green;golangci-lint runclean on all touched packages.tenant1.auth-spike.nixos.defang.ca): register →kid/subreturned, idempotent re-register, same-key-different-stack rejected with 409, list, revoke — all through the newpkg/identityclient.Why draft
Gated on the openauth side: PR 8 landing and the tenant-enabled issuer being deployed at
auth.defang.io. Open questions from #2166 also apply (should/keysrequire a scoped token rather than the plain login token;identity rotateconvenience).🤖 Generated with Claude Code
https://claude.ai/code/session_01R9PbZ9nkj1RxubjnxujXPa